/********************************************
 * 功能说明: AES工具类
 * 模块名称: 工具模块
 * 系统名称: java敏捷开发通用平台
 * 软件版权:
 * 系统版本: 1.0.0
 * 开发人员: zhangfb
 * 开发时间: 2017年6月5日 下午6:24:59
 * 审核人员:
 * 相关文档:
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.hyacinth.codec;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

/**
 * AES工具类
 * AES128算法，加密模式为ECB，填充模式为 pkcs7（实际就是pkcs5）
 * @author zhangfb
 * @version 1.0.0.1
 */
public class AESUtils {
	
	/** 字符集 */
    private static final String CHARSET = "UTF-8";
	/** 密钥算法 */
    private static final String ALGORITHM = "AES";
    
    /** 
     * 加解密算法/工作模式/填充方式 
     */  
    private static final String ALGORITHM_STR = "AES/ECB/PKCS5Padding";  
    
    /** 
     * AES加密 
     * @param plainData 明文数组
     * @param keySpec 秘钥
     * @return 密文数组
     * @throws Exception 
     */  
    public static byte[] encrypt(byte[] plainData, SecretKeySpec keySpec) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM_STR); // 创建密码器  
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);// 初始化  
        return cipher.doFinal(plainData);
    }  
  
    /** 
     * AES解密 
     * @param cipherData 密文数组
     * @param keySpec 秘钥
     * @return 明文数组
     * @throws Exception 
     */
    public static byte[] decrypt(byte[] cipherData, SecretKeySpec keySpec) throws Exception{  
        Cipher cipher = Cipher.getInstance(ALGORITHM_STR);
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        return cipher.doFinal(cipherData);
    }  
    
    /**
     * 字符串加密
     * @param plainText 待加密的字符串
     * @param key 加密的AES Key
     * @return Base64编码的密文字符串
     * @throws Exception 
     */
    public static String encryptString(String plainText, String key) throws Exception {
    	SecretKeySpec keySpec = getSecretKeySpec(key);
        return Base64.encodeBase64String(encrypt(plainText.getBytes(CHARSET), keySpec));
    }

    /**
     * 字符串解密
     * @param cipherText 待解密的Base64编码的密文字符串
     * @param key 密码
     * @return 明文字符串
     * @throws Exception 
     */
    public static String decryptString(String cipherText, String key) {
    	SecretKeySpec keySpec = getSecretKeySpec(key);
    	byte[] cipherData = Base64.decodeBase64(cipherText);
    	byte[] plainData;
		try {
			plainData = decrypt(cipherData, keySpec);
			return new String(plainData, CHARSET);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
    }
    
    /**
     * 获取AES KEY
     * @param password
     * @return
     * @throws NoSuchAlgorithmException
     * @throws UnsupportedEncodingException 
     */
    public static SecretKey getSecretKey(String password) {
    	KeyGenerator kgen = null;
		try {
			kgen = KeyGenerator.getInstance(ALGORITHM);
			kgen.init(128, new SecureRandom(password.getBytes()));
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}

        return kgen.generateKey();
    }
    
    public static String getBase64Key(String password) {
    	SecretKey secretKey = getSecretKey(password);
        return Base64.encodeBase64String(secretKey.getEncoded());
    }
    
    public static String getBase64Key(SecretKey secretKey) {
        return Base64.encodeBase64String(secretKey.getEncoded());
    }
    
    public static SecretKeySpec getSecretKeySpec(SecretKey secretKey) {
    	byte[] enCodeFormat = secretKey.getEncoded();
        return new SecretKeySpec(enCodeFormat, ALGORITHM);
    }
    
    public static SecretKeySpec getSecretKeySpec(String password) {
    	SecretKey secretKey = getSecretKey(password);
        return new SecretKeySpec(secretKey.getEncoded(), ALGORITHM);
    }

    /**将16进制转换为二进制
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length()/2];
        for (int i = 0;i< hexStr.length()/2; i++) {
            int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);
            int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    /**
     * 将二进制转换成16进制
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuilder sb = new StringBuilder();
        for (byte aBuf : buf) {
            String hex = Integer.toHexString(aBuf & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    public static void  main(String aregs[]){
        String content = "qq1987";
        String password = "aghoo.com";
        try {
            //加密
            System.out.println("加密前：" + content);
            String encrypt = AESUtils.encryptString(content, password);
            
            System.out.println("加密后：" + encrypt);
            //解密
            //encrypt = "0Srw8QUPWWdA0en2muV3cw==";
            String decrypt = AESUtils.decryptString(encrypt, password);
            System.out.println("解密后：" + decrypt);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
